package org.joke.manager.gui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.joke.manager.model.Snippet;

public class CodeSnippetView extends JFrame implements ClipboardOwner{

	private static final long serialVersionUID = -5169331878870093347L;

	private JScrollPane scrollPane;
	private JList listSnippets;
	private JPanel panel;
	private JButton btnMenu;
	private JButton btnClear;

	private DefaultListModel listSnippetsModel;

	public CodeSnippetView() {
		initGUI();
	}

	private void initGUI() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.setSize(201, 375);
		getContentPane().setLayout(new BorderLayout(0, 0));

		this.scrollPane = new JScrollPane();
		getContentPane().add(this.scrollPane, BorderLayout.CENTER);

		listSnippetsModel = new DefaultListModel();
		this.listSnippets = new JList(listSnippetsModel) {
			public String getToolTipText(MouseEvent e) {
				int index = locationToIndex(e.getPoint());
				if (-1 < index) {
					Snippet snippet = (Snippet) getModel().getElementAt(index);
					return snippet.getValue();
				} else {
					return null;
				}
			}
		};
		this.scrollPane.setViewportView(this.listSnippets);

		this.panel = new JPanel();
		getContentPane().add(this.panel, BorderLayout.SOUTH);
		this.panel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

		this.btnMenu = new JButton("Menu");
		btnMenu.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				createMainPopupMenu(e);
			}
		});
		this.panel.add(this.btnMenu);

		this.btnClear = new JButton("Clear");
		btnClear.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				clearItems();
			}

			
		});
		this.panel.add(this.btnClear);

		listSnippets.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == e.BUTTON3) {
					createListPopupMenu(e);
				}
			}

		});
		
		listSnippets.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				Clipboard clipboard = Toolkit.getDefaultToolkit()
				.getSystemClipboard();
				Object selected = listSnippetsModel.getElementAt(listSnippets.getSelectedIndex());
				if(selected!=null && selected instanceof Snippet){
					clipboard.setContents(new StringSelection(((Snippet)selected).getValue()),CodeSnippetView.this);
				}
			}
		});
	}

	private void clearItems() {
		listSnippetsModel.clear();
		Snippet.counter = 0;
	}
	
	protected void createMainPopupMenu(MouseEvent e) {
		JPopupMenu menu = new JPopupMenu();

		JMenuItem itemSaveSnippets = new JMenuItem("Save current snippets");
		itemSaveSnippets.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				saveSnippets();
			}
		});
		menu.add(itemSaveSnippets);

		JMenuItem itemLoadSnippets = new JMenuItem("Load current snippets");
		itemLoadSnippets.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				loadSnippets();
			}
		});
		menu.add(itemLoadSnippets);
		
		JMenuItem itemClearSnippets = new JMenuItem("Clear current snippets");
		itemClearSnippets.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				clearItems();
			}
		});
		menu.add(itemClearSnippets);
		
		JMenuItem itemExitSnippets = new JMenuItem("Exit snippet manager");
		itemExitSnippets.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.exit(0);
			}
		});
		menu.add(itemExitSnippets);
		
		Point pt = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(),
				e.getComponent());
		menu.show(e.getComponent(), pt.x, pt.y);
	}

	protected void loadSnippets() {
		JFileChooser fileChooser= new JFileChooser();
		int result = fileChooser.showOpenDialog(this);
		if(result == JFileChooser.APPROVE_OPTION){
			listSnippetsModel.clear();
			try {
				File selectedFile = fileChooser.getSelectedFile();
				XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(
			            new FileInputStream(selectedFile)));

				ArrayList<Object> currentSnippetsList = (ArrayList<Object>) decoder.readObject();
				for(Object snippet : currentSnippetsList){
					listSnippetsModel.addElement(snippet);
				}
				decoder.close();


			} catch (FileNotFoundException e) {
				JOptionPane.showMessageDialog(CodeSnippetView.this, e.getMessage());
			}
		}
		
	}

	protected void saveSnippets() {
		JFileChooser fileChooser= new JFileChooser();
		int result = fileChooser.showSaveDialog(this);
		if(result == JFileChooser.APPROVE_OPTION){
			try {
				File selectedFile = fileChooser.getSelectedFile();
				XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(
				        new FileOutputStream(selectedFile)));
				ArrayList<Object> currentSnippetsList = new ArrayList<Object>();
				for (int i = 0; i < listSnippetsModel.size(); i++) {
					currentSnippetsList.add(listSnippetsModel.getElementAt(i));
				}
				encoder.writeObject(currentSnippetsList);
		        encoder.close();

			} catch (FileNotFoundException e) {
				JOptionPane.showMessageDialog(CodeSnippetView.this, e.getMessage());
			}
		}
	}

	private void createListPopupMenu(MouseEvent e) {
		JPopupMenu menu = new JPopupMenu();

		JMenuItem itemInsertSnippet = new JMenuItem("insert snippet");
		itemInsertSnippet.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Clipboard clipboard = Toolkit.getDefaultToolkit()
						.getSystemClipboard();
				try {
					Snippet snippet = new Snippet(String.valueOf(clipboard
							.getData(DataFlavor.stringFlavor)));
					listSnippetsModel.addElement(snippet);
				} catch (UnsupportedFlavorException e1) {
					JOptionPane.showMessageDialog(CodeSnippetView.this,
							"unknown data flavor");
				} catch (IOException e1) {
					JOptionPane.showMessageDialog(CodeSnippetView.this,
							"unknown data flavor");
				}
			}
		});
		menu.add(itemInsertSnippet);
		
		JMenuItem itemDeleteSnippet = new JMenuItem("delete snippet");
		itemDeleteSnippet.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(listSnippets.getSelectedIndex()!=-1){
					int selectedIndex = listSnippets.getSelectedIndex();
					for(int i=listSnippets.getSelectedIndex();i<listSnippets.getModel().getSize();i++){
						if(listSnippets.getModel().getElementAt(i) instanceof String){ // than it is the separator
							break;
						}
	                    Snippet item =(Snippet) listSnippetsModel.getElementAt(i);
	                    item.setId(item.getId()-1);
					}
					listSnippetsModel.remove(selectedIndex);
	                Snippet.counter = Snippet.counter - 1;
				}
			}
		});
		menu.add(itemDeleteSnippet);
		
		menu.add(new JMenuItem("rename snippet"));
		JMenuItem itemSeparatorSnippet = new JMenuItem("insert separator");
		itemSeparatorSnippet.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				listSnippetsModel.addElement(" ------------------------------- ");
				Snippet.counter = 0;
			}
		});
		menu.add(itemSeparatorSnippet);
		
		Point pt = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(),
				e.getComponent());
		menu.show(e.getComponent(), pt.x, pt.y);
	}

	@Override
	public void lostOwnership(Clipboard arg0, Transferable arg1) {
		System.out.println("Clipboard contents replaced");
	}
}
